package com.green.service.export;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;

import com.green.common.util.StringUtil;


public class ExcelExportTool {
	private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd");
	public static HSSFWorkbook exportExcel(ExportView view,ExportDataProvider provider){
		provider.init();
		HSSFWorkbook wb = new HSSFWorkbook();
		if(view != null){
			HSSFSheet sheet = wb.createSheet(StringUtil.isEmpty(view.getName())?"sheet1":view.getName());
			createHead(sheet,view);
			createBody(sheet,view,provider);
		}
		return wb;
	}

	private static void createBody(HSSFSheet sheet, ExportView view,
			ExportDataProvider provider) {
		if(provider != null && provider.getElements() != null){
			if(provider.getElements() instanceof Collection){
				Collection<?> c = (Collection<?>) provider.getElements();
				Iterator<?> iterator = c.iterator();
				Object data;
				HSSFRow row;
				while(iterator.hasNext()){
					data = iterator.next();
					row = sheet.createRow(sheet.getLastRowNum() + 1);
					fillDataToRow(data,view,provider,row);
				}
			}else if(provider.getElements().getClass().isArray()){
				Object[] datas = (Object[]) provider.getElements();
				HSSFRow row;
				for(Object data : datas){
					row = sheet.createRow(sheet.getLastRowNum() + 1);
					fillDataToRow(data,view,provider,row);
				}
			}
		}
	}

	private static void fillDataToRow(Object data, ExportView view,ExportDataProvider provider, HSSFRow row) {
		if(view.getExportItems()!=null && view.getExportItems().size()>0){
			Iterator<ExportItem> iterator = view.getExportItems().iterator();
			ExportItem item;
			int celnum = 0;
			HSSFCell cell;
			while(iterator.hasNext()){
				item = iterator.next();
				cell = row.createCell(celnum);
				cell.setCellType(Cell.CELL_TYPE_STRING);
				cell.setCellValue(getValueFromObject(view,provider,data,item.getName()));
				celnum++;
			}
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private static String getValueFromObject(ExportView view,ExportDataProvider provider,Object data, String name) {
		if(!StringUtil.isEmpty(name)){
			String[] fields = name.split("\\.");
			Object tmp = data;
			String getter;
			Class cls;
			Method method;
			for(String field : fields){
				if(tmp instanceof Map){
					tmp = ((Map)tmp).get(field);
				}else{
					if(field.length()>0){
						getter = "get"+field.substring(0,1).toUpperCase()+field.substring(1);
						cls = tmp.getClass();
						try {
							method = cls.getMethod(getter, new Class[]{});
							tmp = method.invoke(tmp, new Object[]{});
						} catch (Exception e) {
							if(e instanceof NoSuchMethodException){
								getter = "is" + getter.substring(3);
								try {
									method = cls.getMethod(getter, new Class[]{});
									tmp = method.invoke(tmp, new Object[]{});
								} catch (Exception e1) {
									return "";
								}
							}
						}
					}else{
						return "";
					}
				}
				if(tmp==null){
					return "";
				}
			}
			if(tmp!=null){
				if(provider.existsRender(name)){
					return provider.getRender(name).getAsString(tmp);
				}
				return objectToString(tmp);
			}
			return "";
		}
		return "";
	}

	private static void createHead(HSSFSheet sheet, ExportView view) {
		if(view.getExportItems()!=null && view.getExportItems().size()>0){
			Iterator<ExportItem> iterator = view.getExportItems().iterator();
			ExportItem item;
			int celnum = 0;
			HSSFRow row = sheet.createRow(sheet.getLastRowNum());
			HSSFCell cell;
			while(iterator.hasNext()){
				item = iterator.next();
				cell = row.createCell(celnum);
				cell.setCellValue(item.getDisplay());
				sheet.setColumnWidth(celnum, item.getWidth());
				celnum++;
			}
		}
	}
	
	private static String objectToString(Object obj){
		if(obj==null){
			return null;
		}
		if(obj instanceof Date){
			return SDF.format((Date)obj);
		}
		return obj.toString();
	}
}
